﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace PhoneCrawler
{
    public class BaiduWebCrawler : WebCrawler
    {
        public BaiduWebCrawler() : base()
        {
            httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36");
        }

        public override async Task<Dictionary<string, List<string>>> Search(string keyword)
        {
            string encodeUrl = System.Net.WebUtility.UrlEncode(keyword);
            string baiduUrl = $"https://www.baidu.com/s?wd={encodeUrl}";
            return await base.SearchAsync(baiduUrl);
        }
    }

    public class BingWebCrawler : WebCrawler
    {
        public BingWebCrawler() : base()
        {
            // 不设置 UserAgent
        }

        public override async Task<Dictionary<string, List<string>>> Search(string keyword)
        {
            string encodeUrl = System.Net.WebUtility.UrlEncode(keyword);
            string bingUrl = $"https://www.bing.com/search?q={encodeUrl}";
            return await base.SearchAsync(bingUrl);
        }
    }

    public abstract class WebCrawler
    {
        protected readonly HttpClient httpClient;
        protected HashSet<string> crawledUrls; // 用于去重
        protected const int MaxPhoneNumbers = 100; // 目标电话号码数量

        public WebCrawler()
        {
            httpClient = new HttpClient();
            crawledUrls = new HashSet<string>();
        }

        public abstract Task<Dictionary<string, List<string>>> Search(string keyword);

        protected async Task<Dictionary<string, List<string>>> SearchAsync(string url)
        {
            var results = new Dictionary<string, List<string>>();
            var searchResultsHtml = await httpClient.GetStringAsync(url);
            var resultUrls = ExtractResultUrls(searchResultsHtml);

            foreach (var resultUrl in resultUrls)
            {
                // 达到100个电话号码则停止
                int totalPhoneNumbers = results.Values.Sum(phoneNumbers => phoneNumbers.Count);
                if (totalPhoneNumbers >= MaxPhoneNumbers)
                {
                    break;
                }

                var phoneNumbers = await ExtractPhoneNumbersFromUrl(resultUrl);
                if (phoneNumbers.Count > 0)
                {
                    results[resultUrl] = phoneNumbers;
                    crawledUrls.Add(resultUrl); // 添加已爬取的URL
                }
            }
            return results;
        }

        private List<string> ExtractResultUrls(string html)
        {
            var urls = new List<string>();
            var regex = new Regex(@"<a\s+(?:[^>]*?\s+)?href=""(https?://[^""]+)""|<link\s+(?:[^>]*?\s+)?href=""(https?://[^""]+)"""); // 提取URL
            var matches = regex.Matches(html);

            foreach (Match match in matches)
            {
                string url = match.Groups[1].Value;
                if (!urls.Contains(url) && !crawledUrls.Contains(url)) // 去重
                {
                    urls.Add(url);
                }
            }
            return urls;
        }

        private async Task<List<string>> ExtractPhoneNumbersFromUrl(string url)
        {
            try
            {
                var phoneNumbers = new List<string>();
                var html = await httpClient.GetStringAsync(url);
                var regex = new Regex(@"\b\d{3}[-.\s]?\d{4}[-.\s]?\d{4}\b|\b\d{3}[-.\s]?\d{4}\b|\b\d{3}[-.\s]?\d{5}\b|\b\d{3}[-.\s]?\d{8}\b|\b\d{3}[-.\s]?\d{3}[-.\s]?\d{4}\b"); // 提取电话号码
                var matches = regex.Matches(html);

                foreach (Match match in matches)
                {
                    string number = match.Value;
                    if (!phoneNumbers.Contains(number)) // 去重
                    {
                        phoneNumbers.Add(number);
                    }
                }
                return phoneNumbers;
            }
            catch (Exception)
            {
                return new List<string>();
            }
        }
    }
}
